/*
 * Copyright 2007-2008 Andrew O'Malley
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


package ws.quokka.plugin.junitreport;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.taskdefs.Delete;
import org.apache.tools.ant.taskdefs.TempFile;
import org.apache.tools.ant.taskdefs.XSLTProcess;
import org.apache.tools.ant.taskdefs.optional.junit.AggregateTransformer;
import org.apache.tools.ant.taskdefs.optional.junit.XMLResultAggregator;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.util.FileUtils;

import ws.quokka.core.plugin_spi.support.AbstractPlugin;
import ws.quokka.core.plugin_spi.support.ResourcesList;
import ws.quokka.core.plugin_spi.support.Setter;

import ws.quokka.plugin.devreport.DevReportHelper;

import java.io.File;

import java.util.Iterator;


/**
 *
 */
public class JunitReportPlugin extends AbstractPlugin {
    //~ Static fields/initializers -------------------------------------------------------------------------------------

    private static int counter = 0;

    //~ Instance fields ------------------------------------------------------------------------------------------------

    private DevReportHelper helper;

    //~ Methods --------------------------------------------------------------------------------------------------------

    public void initialise() {
        super.initialise();
        helper = new DevReportHelper(getResources(), properties(), log());
    }

    public void collect() {
        helper.addResource(properties().getFileSet("tests"));

        if (properties().getBoolean("propogate")) {
            propogate();
        }
    }

    public void propogate() {
        helper.propogateResources();
    }

    public void report() {
        helper.addReport();
        report(helper.getLocalResources());
    }

    public void aggregateReport() {
        helper.addReport();
        report(helper.getAggregatedResources());
    }

    private void report(ResourcesList tests) {
        Aggregator junitReport = (Aggregator) utils().init(new Aggregator(), "junitreport");

        File dir = properties().getFile("toDir");
        utils().mkdir(dir);

        Setter setter = new Setter(properties());
        setter.set(junitReport, new String[] { "tofile", "toDir" });

        AggregateTransformer report = junitReport.createReport();
        setter = new Setter(properties().sub("report."));
        setter.set(report, new String[] { "format", "styleDir", "toDir" });

        for (Iterator i = tests.getNested().iterator(); i.hasNext();) {
            junitReport.addFileSet((FileSet)i.next());
        }

        junitReport.perform();
        log().info("Generated report to: " + new File(dir.getAbsolutePath(), "index.html").getAbsolutePath());
    }

    //~ Inner Classes --------------------------------------------------------------------------------------------------

    public class Aggregator extends XMLResultAggregator {
        public AggregateTransformer createReport() {
            Transformer transformer = new Transformer(this);
            transformers.addElement(transformer);

            return transformer;
        }
    }

    public class Transformer extends AggregateTransformer {
        public Transformer(Task task) {
            super(task);
        }

        public void transform() throws BuildException {
            //            System.out.println("JunitReportPlugin$Transformer.transform");
            checkOptions();

            Project project = task.getProject();

            TempFile tempFileTask = new TempFile();
            tempFileTask.bindToOwner(task);

            XSLTProcess xsltTask = new XSLTProcess();
            xsltTask.bindToOwner(task);

            Path classpath = getResources().getPathGroupAsPath("classpath");
            xsltTask.setClasspath(classpath);

            xsltTask.setXslResource(getStylesheet());

            // acrobatic cast.
            xsltTask.setIn(((XMLResultAggregator)task).getDestinationFile());

            File outputFile;

            if (format.equals(FRAMES)) {
                String tempFileProperty = getClass().getName() + String.valueOf(counter++);
                File tmp = FileUtils.getFileUtils().resolveFile(project.getBaseDir(),
                        project.getProperty("java.io.tmpdir"));
                tempFileTask.setDestDir(tmp);
                tempFileTask.setProperty(tempFileProperty);
                tempFileTask.execute();
                outputFile = new File(project.getProperty(tempFileProperty));
            } else {
                outputFile = new File(toDir, "junit-noframes.html");
            }

            xsltTask.setOut(outputFile);

            // TODO: Support XSLT params
            //            for (Iterator i = params.iterator(); i.hasNext();) {
            //                XSLTProcess.Param param = (XSLTProcess.Param) i.next();
            //                XSLTProcess.Param newParam = xsltTask.createParam();
            //                newParam.setProject(task.getProject());
            //                newParam.setName(param.getName());
            //                newParam.setExpression(param.getExpression());
            //            }
            XSLTProcess.Param paramx = xsltTask.createParam();
            paramx.setProject(task.getProject());
            paramx.setName("output.dir");
            paramx.setExpression(toDir.getAbsolutePath());

            //            final long t0 = System.currentTimeMillis();
            try {
                xsltTask.execute();
            } catch (Exception e) {
                throw new BuildException("Errors while applying transformations: " + e.getMessage(), e);
            }

            //            final long dt = System.currentTimeMillis() - t0;
            //            task.log("Transform time: " + dt + "ms");
            if (format.equals(FRAMES)) {
                Delete delete = new Delete();
                delete.bindToOwner(task);
                delete.setFile(outputFile);
                delete.execute();
            }
        }
    }
}
